/**********************************************
*  Namespace: AI
*  Classes:   Steering
*  Desc:      Updates positions using a steering
*             algorithm in 2d or 3d cases
*  Structs:   Kinematic2d, Kinematic3d.
*			  Steering3d, Steering3d
*  Desc:      Structs that hold information
*             used by steering behaviors in 2d and 3d
*  Author:    Vaios Kalpias-Ilias (C) 2008-2009
***********************************************/

#ifndef STEERING_H
#define STEERING_H

#include "Vector.h"
#include "Quaternion.h"

namespace AI
{
	// constants
	const float maxAcceleration = 0.1f;
	const float maxSpeed = 0.1f;
	const float targetRadius = 1.0f;
	const float slowRadius = 5.0f;
	const float timeToTarget = 1.0f;
	const float maxAngularAcceleration = 0.01f;
    const float maxRotation = 0.1f;
    const float rotationTargetRadius = 0.1f;
	const float rotationSlowRadius = 1.8f;
	const float rotationTimeToTarget = 1.0f;
	const float maxPrediction = 0.01f;
	const float collisionRadius = 5.0f;
	const float velocityDamping = 0.00001f;
	const float rotationDamping = 0.00001f;
	
	//------------------------------------
	typedef struct kinematic2d_t
	{
		mth::Vector2 position;
		mth::Vector2 velocity;
		float   orientation;
		float   rotation;

		kinematic2d_t() : position(),
						  velocity(),
						  orientation(0.0f),
						  rotation(0.0f)
		{}

		kinematic2d_t(const mth::Vector2& pos,
					  const mth::Vector2& vel,
					  float orient,
					  float rot) : position(pos),
										velocity(vel),
										orientation(orient),
										rotation(rot)
		{}

		kinematic2d_t(const kinematic2d_t& k) : position(k.position),
												velocity(k.velocity),
												orientation(k.orientation),
												rotation(k.rotation)
		{}



	} Kinematic2d;

	//------------------------------------
	typedef struct steering2d_t
	{
		mth::Vector2 linear;
		float   angular;

		steering2d_t() : linear(0.0f,0.0f), angular(0.0f)
		{}

		steering2d_t(const mth::Vector2& lin,
			         float ang) :
										linear(lin), 
									    angular(ang)
		{}

		steering2d_t(const steering2d_t& s) :

										linear(s.linear), 
										angular(s.angular)
		{}
	} Steering2d;

	//------------------------------------
	typedef struct kinematic3d_t
	{
		mth::Vector3 position;
		mth::Vector3 velocity;
		mth::Quaternion orientation;
		float rotation;

		kinematic3d_t() : position(),
						  velocity(),
						  orientation(),
						  rotation(0.0f)
		{}

		kinematic3d_t(const mth::Vector3& pos,
					  const mth::Vector3& vel,
					  const mth::Quaternion& orient,
					  float rot) : 
		                                position(pos),
										velocity(vel),
										orientation(orient),
										rotation(rot)
		{}

		kinematic3d_t(const kinematic3d_t& k) : position(k.position),
												velocity(k.velocity),
												orientation(k.orientation),
												rotation(k.rotation)
		{}

	} Kinematic3d;

	//------------------------------------
	typedef struct steering3d_t
	{
		mth::Vector3 linear;
		float            angular;

		steering3d_t() : linear(), angular(0.0f)
		{}

		steering3d_t(const mth::Vector3& lin,
			         float ang) :
										linear(lin), 
									    angular(ang)
		{}

		steering3d_t(const steering3d_t& s) :

										linear(s.linear), 
										angular(s.angular)
		{}

	} Steering3d;

	//------------------------------------

	class Steering
	{
	public:
		// 2d

		// update kinematic data
		static void Update(Kinematic2d& kinematic, 
			        Steering2d& steering,
					float dt);
		
		
		
		// 3d

		// update kinematic data
		static void Update(Kinematic3d& kinematic, 
			        const Steering3d& steering,					
					float dt);

		
		
	protected:
		Steering();
		virtual ~Steering();
		
	};
}


#endif